package topic

import (
	"company_website/src/global"
	"company_website/src/model"
	"company_website/src/model/common"
	"company_website/src/model/request"
	"company_website/src/model/response"
	"company_website/src/utils"
	"encoding/json"
	"errors"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"os"
	"path"
	"time"
)

type Topic struct {
}

func (t Topic) GetThreeTopic(c *gin.Context) {
	var topic []response.NewTopic
	err := global.GVL_DB.Model(&model.Topic{}).Where("topic.release=?", 1).Select("id,url,title,content").Order("time desc").Limit(3).Find(&topic).Error
	if err != nil {
		global.GVL_LOG.Error("获取topic数据错误:", err)
		response.FailWithMessage("获取topic数据错误"+err.Error(), c)
		return
	}
	response.OkWithData(topic, c)
}
func (t Topic) GetTopicDetailsById(c *gin.Context) {
	var topicId request.GetTopicByIdModel
	if err := c.ShouldBindJSON(&topicId); err != nil {
		global.GVL_LOG.Error("接收json数据错误:", err)
		response.FailWithMessage("接收json数据错误", c)
		return
	}
	var topicDetails []response.TopicDetails
	err := global.GVL_DB.Model(&model.Topic{}).
		Select("topic.id,admin.admin_name,topic.url,topic.title,topic.content,topic.time").Joins("join admin on topic.admin_id=admin.id").
		Where("topic.release=1 and topic.id=?", topicId.Id).
		Find(&topicDetails).Error
	if err != nil {
		global.GVL_LOG.Error("获取topic数据错误:", err)
		response.FailWithMessage("获取topic数据错误", c)
		return
	}
	//如果传递过来的id没有对应的数据
	if len(topicDetails) == 0 {
		response.FailWithMessage("没有找到对应数据", c)
		return
	}
	response.OkWithData(topicDetails, c)
}
func (t Topic) GetPageTopic(c *gin.Context) {
	var pageReq common.PageReqInfo
	if err := c.ShouldBindJSON(&pageReq); err != nil {
		global.GVL_LOG.Error("接收json数据错误:", err)
		response.FailWithMessage("接收json数据错误", c)
		return
	} else if pageReq.CurrentPage < 1 {
		response.FailWithMessage("请输入正确页数", c)
		return
	} else {
		pageReq.CurrentPage = (pageReq.CurrentPage - 1) * pageReq.PageSize
	}
	var pageTopic []response.PageTopic
	if err := global.GVL_DB.Model(&model.Topic{}).Select("url,title,content").
		Where("topic.release=1").
		Offset(pageReq.CurrentPage).Limit(pageReq.PageSize).Find(&pageTopic).Error; err != nil {
		global.GVL_LOG.Error("获取topic数据错误:", err)
		response.FailWithMessage("获取topic数据错误", c)
		return
	}
	if len(pageTopic) == 0 {
		response.FailWithMessage("没有找到对应数据", c)
		return
	}
	response.OkWithData(pageTopic, c)
}
func (t Topic) GetTopicByCategory(c *gin.Context) {
	var param request.GetTopicByCategoryModel
	if err := c.ShouldBindJSON(&param); err != nil {
		global.GVL_LOG.Error("接收json数据错误:", err)
		response.FailWithMessage("接收json数据错误", c)
		return
	} else if param.CurrentPage < 1 {
		response.FailWithMessage("请输入正确页数", c)
		return
	} else {
		param.CurrentPage = (param.CurrentPage - 1) * param.PageSize
	}
	var topic []response.NewTopic
	if err := global.GVL_DB.Model(&model.Topic{}).Select("DISTINCT topic.id,url,title,content").
		Joins("join topic_category on topic_category.topic_id= topic.id").
		Joins("join category on topic_category.category_id= category.id").
		Where("topic.release=1 and category.category like ?", "%"+param.Category+"%").
		Offset(param.CurrentPage).Limit(param.PageSize).
		Find(&topic).Error; err != nil {
		global.GVL_LOG.Error("获取topic数据错误:", err)
		response.FailWithMessage("获取topic数据错误", c)
		return
	}
	if len(topic) == 0 {
		response.FailWithMessage("没有找到对应数据", c)
		return
	}
	response.OkWithData(topic, c)
}
func (t Topic) GetTopicByTitle(c *gin.Context) {
	var param request.GetTopicByTitleModel
	if err := c.ShouldBindJSON(&param); err != nil {
		global.GVL_LOG.Error("接收json数据错误:", err)
		response.FailWithMessage("接收json数据错误", c)
		return
	}
	var topic []response.NewTopic
	if err := global.GVL_DB.Model(&model.Topic{}).Select("id,url,title,content").
		Where("topic.release=1 and title like ?", "%"+param.Title+"%").Find(&topic).Error; err != nil {
		global.GVL_LOG.Error("获取topic数据错误:", err)
		response.FailWithMessage("获取topic数据错误", c)
		return
	}
	if len(topic) == 0 {
		response.FailWithMessage("没有找到对应数据", c)
		return
	}
	response.OkWithData(topic, c)
}
func (t Topic) AddTopic(c *gin.Context) {
	//获取登录的管理员信息和查看是否有对应权限
	//Authorization := c.Request.Get("Authorization")
	//UserInfo,_ = server.AdminUser.GetUserToRedis(Authorization)
	//================================
	var topic request.AddTopicModel
	//if err := c.ShouldBindJSON(&topic); err != nil {
	//	global.GVL_LOG.Error("接收json数据错误:", err)
	//	response.FailWithMessage("接收json数据错误", c)
	//	return
	//}
	// 从表单中获取JSON数据字符串
	jsonData := c.PostForm("jsonData")
	// 解析JSON字符串到结构体
	err := json.Unmarshal([]byte(jsonData), &topic)
	if err != nil {
		// 处理JSON解析错误...
		global.GVL_LOG.Error("JSON解析错误:", err)
		response.FailWithMessage("JSON解析错误", c)
		return
	}
	// 从请求中获取文件
	file, err := c.FormFile("image")
	if err != nil {
		global.GVL_LOG.Error("接收图片错误", err)
		response.FailWithMessage("接收图片错误", c)
		return
	}
	imgpath := path.Join(global.GVL_CFG.Local.TopicUrl, utils.GetFileName(file.Filename))
	// 保存文件到服务器
	err = c.SaveUploadedFile(file, imgpath)
	if err != nil {
		global.GVL_LOG.Error("保存图片错误", err)
		response.FailWithMessage("保存图片错误", c)
		return
	}
	//开启一个原子操作
	if err := global.GVL_DB.Transaction(func(tx *gorm.DB) error {
		//添加topic表信息
		newTopic := model.Topic{
			AdminId: 1, //需要登录信息转化为对应的管理员
			Url:     imgpath,
			Title:   topic.Title,
			Content: topic.Content,
			Release: 0,
			Time:    time.Now().Unix(),
		}
		//这里更改了数据库time的类型
		if err := global.GVL_DB.Model(&model.Topic{}).Create(&newTopic).Error; err != nil {
			return err
		}
		//添加category表信息
		newCategory := model.Category{}
		//应当先查找分类表中是否已经存在分类，如果有则无需增加新得记录，没有则添加记录
		if err := global.GVL_DB.Model(&model.Category{}).
			Where("category=?", topic.Category).First(&newCategory).Error; err != nil {
			if errors.Is(err, gorm.ErrRecordNotFound) {
				// 空错误，说明数据库中没有找到记录，可以添加新记录
				newCategory.Category = topic.Category
				if err := global.GVL_DB.Create(&newCategory).Error; err != nil {
					return err
				}
			} else {
				// 其他错误，返回错误
				return err
			}
		}
		//添加中间表topic_category表信息
		newConnect := model.TopicCategory{
			TopicId:    newTopic.Id,
			CategoryId: newCategory.Id,
		}
		if err := global.GVL_DB.Create(&newConnect).Error; err != nil {
			return err
		}
		return nil
	}); err != nil {
		//数据库中数据添加失败，应当删除已经添加的图片，以保持数据库与静态文件的数据一致性
		if _, err := os.Stat(imgpath); os.IsNotExist(err) {
			global.GVL_LOG.Warn("删除的图片不存在")
		} else if err != nil {
			// 处理 os.Stat 调用中可能发生的其他错误
			global.GVL_LOG.Error("检查图片存在性时发生错误:", err)
		} else {
			// 文件存在，尝试删除
			err := os.Remove(imgpath)
			if err != nil {
				global.GVL_LOG.Error("删除图片错误:", err)
			}
		}
		global.GVL_LOG.Error("添加topic原子操作失败", err)
		response.FailWithMessage("添加失败", c)
		return
	}
	response.OkWithMessage("添加成功", c)

}
func (t Topic) ModifyTopic(c *gin.Context) {
	//获取登录的管理员信息并比对是否和编辑该话题的管理员一致（或者是超级管理员）
	//从form表单中获取json字符串和图片
	var UpdateTopic request.ModifyTopicModel
	// 从表单中获取JSON数据字符串
	jsonData := c.PostForm("jsonData")
	// 解析JSON字符串到结构体
	err := json.Unmarshal([]byte(jsonData), &UpdateTopic)
	if err != nil {
		// 处理JSON解析错误...
		global.GVL_LOG.Error("JSON解析错误:", err)
		response.FailWithMessage("JSON解析错误", c)
		return
	}
	// 从请求中获取文件
	file, err := c.FormFile("image")
	if err != nil {
		global.GVL_LOG.Error("接收图片错误", err)
		response.FailWithMessage("接收图片错误", c)
		return
	}
	//更新图片
	//1.删除原先的图片
	var imgpath string
	if err := global.GVL_DB.Model(&model.Topic{}).
		Select("url").
		Where("id=?", UpdateTopic.Id).First(&imgpath).Error; err != nil {
		global.GVL_LOG.Error("寻找话题错误:", err)
		response.FailWithMessage("话题不存在", c)
		return
	}
	// 检查文件是否存在
	if _, err := os.Stat(imgpath); os.IsNotExist(err) {
		global.GVL_LOG.Warn("删除的图片不存在")
	} else if err != nil {
		// 处理 os.Stat 调用中可能发生的其他错误
		global.GVL_LOG.Error("检查图片存在性时发生错误:", err)
	} else {
		// 文件存在，尝试删除
		err := os.Remove(imgpath)
		if err != nil {
			global.GVL_LOG.Error("删除图片错误:", err)
		}
	}
	//2.增加图片
	//更新图片路径
	imgpath = path.Join(global.GVL_CFG.Local.TopicUrl, utils.GetFileName(file.Filename))
	err = c.SaveUploadedFile(file, imgpath)
	if err != nil {
		global.GVL_LOG.Error("保存图片错误", err)
		response.FailWithMessage("保存图片错误", c)
		return
	}
	//更新文章分类
	if err := global.GVL_DB.Transaction(func(tx *gorm.DB) error {
		//1.删除原有的分类信息（在topic_category表中删除所有符合topic.id的字段）
		if err := tx.Where("topic_id=?", UpdateTopic.Id).Delete(&model.TopicCategory{}).Error; err != nil {
			return err
		}
		//2.添加文章分类信息
		//添加分类信息时先检查category表里是否已经拥有该分类，如果有则获取在category表中的id，没有则新增分类字段再获取category表中的id
		var category model.Category
		// 尝试查找分类是否存在
		if err := tx.Where("category = ?", UpdateTopic.Category).First(&category).Error; err != nil {
			if errors.Is(err, gorm.ErrRecordNotFound) {
				// 分类不存在，创建新的分类
				category.Category = UpdateTopic.Category
				if err := tx.Create(&category).Error; err != nil {
					return err
				}
			} else {
				// 其他错误
				return err
			}
		}
		topicCate := model.TopicCategory{
			TopicId:    UpdateTopic.Id,
			CategoryId: category.Id,
		}
		if err := tx.Model(&model.TopicCategory{}).Create(&topicCate).Error; err != nil {
			return err
		}
		//更新文章剩余内容
		topic := model.Topic{}
		if err := tx.Where("id=?", UpdateTopic.Id).First(&topic).Error; err != nil {
			return err
		}
		topic.Title = UpdateTopic.Title
		topic.Content = UpdateTopic.Content
		topic.Url = imgpath
		if err := tx.Save(&topic).Error; err != nil {
			return err
		}
		return nil
	}); err != nil {
		global.GVL_LOG.Error("修改topic原子操作失败", err)
		response.FailWithMessage("修改失败", c)
		return
	}
	response.OkWithMessage("修改成功", c)
}
func (Topic) DeleteTopic(c *gin.Context) {
	//1.查看管理员是否有权限（是添加话题的管理员或者是超级管理员）

	var deleteId request.DeleteTopicByIdModel
	if err := c.ShouldBindJSON(&deleteId); err != nil {
		global.GVL_LOG.Error("接收json数据错误:", err)
		response.FailWithMessage("接收json数据错误", c)
		return
	}
	if err := global.GVL_DB.Transaction(func(tx *gorm.DB) error {
		//2.删除topic_category表中删除所有符合topic.id的字段
		//先查看有没有存在对应的话题
		var topic model.Topic
		if err := tx.Model(&model.Topic{}).Where("id=?", deleteId.Id).First(&topic).Error; err != nil {
			if errors.Is(err, gorm.ErrRecordNotFound) {
				response.FailWithMessage("没有找到对应话题", c)
				return err
			} else {
				//其他错误
				return err
			}
		}
		if err := tx.Model(&model.TopicCategory{}).Where("topic_id=?", deleteId.Id).Delete(&model.TopicCategory{}).Error; err != nil {
			return err
		}
		//3.删除topic表中的字段
		if err := tx.Model(&model.Topic{}).Where("id=?", deleteId.Id).Delete(&model.Topic{}).Error; err != nil {
			return err
		}
		//4.删除关联的图片
		// 检查文件是否存在
		if _, err := os.Stat(topic.Url); os.IsNotExist(err) {
			global.GVL_LOG.Warn("删除的图片不存在")
		} else if err != nil {
			// 处理 os.Stat 调用中可能发生的其他错误
			global.GVL_LOG.Error("检查图片存在性时发生错误:", err)
		} else {
			// 文件存在，尝试删除
			err := os.Remove(topic.Url)
			if err != nil {
				global.GVL_LOG.Error("删除图片错误:", err)
				//删除失败时回滚数据库数据
				return err
			}
		}
		return nil
	}); err != nil {
		response.FailWithMessage("删除失败", c)
	}
	response.OkWithMessage("删除成功", c)
}
func (t Topic) ReleaseTopic(c *gin.Context) {
	//1.查看管理员是否有权限（是添加话题的管理员或者是超级管理员）

	var ReleaseId request.ReleaseTopicByIdModel
	if err := c.ShouldBindJSON(&ReleaseId); err != nil {
		global.GVL_LOG.Error("接收json数据错误:", err)
		response.FailWithMessage("接收json数据错误", c)
		return
	}
	var topic model.Topic
	if err := global.GVL_DB.Model(&model.Topic{}).Where("id=?", ReleaseId.Id).First(&topic).Error; err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			response.FailWithMessage("没有找到对应话题", c)
			return
		} else {
			//其他错误
			global.GVL_LOG.Error("查找topic数据错误", err)
			return
		}
	}
	topic.Release = 1
	topic.Time = time.Now().Unix()
	if err := global.GVL_DB.Save(&topic).Error; err != nil {
		global.GVL_LOG.Error("topic更新失败", err)
		response.FailWithMessage("发布失败", c)
		return
	}
	response.OkWithMessage("发布成功", c)
}
